/*
 * Allwinner H3 UART
 *
 * Copyright (c) 2025 yanl1229 <yanl1229@163.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef HW_ALLWINNER_H3_UART_H
#define HW_ALLWINNER_H3_UART_H

#include "hw/sysbus.h"
#include "qemu/fifo8.h"
#include "chardev/char-fe.h"

#define UART_RBR    0x00
#define UART_THR    0x00
#define UART_DLL    0x00
#define UART_DLH    0x04
#define UART_IER    0x04
#define UART_IIR    0x08
#define UART_FCR    0x08
#define UART_LCR    0x0c
#define UART_MCR    0x10
#define UART_LSR    0x14
#define UART_MSR    0x18
#define UART_SCH    0x1c
#define UART_USR    0x7c
#define UART_TFL    0x80
#define UART_RFL    0x84
#define UART_HALT   0xa4


#define UART_LCR_DLAB	(0x1 << 7)

#define UART_IER_MSI	(0x1 << 3)
#define UART_IER_RLSI	(0x1 << 2)
#define UART_IER_THRI	(0x1 << 1)
#define UART_IER_RDI	(0x1 << 0)

#define UART_IIR_NO_INT	(0x1 << 0)
#define UART_IIR_ID	    0x06

#define UART_IIR_MSI	0x00
#define UART_IIR_THRI	0x02
#define UART_IIR_RDI	0x04
#define UART_IIR_RLSI	0x06
#define UART_IIR_CTI    0x0C

#define UART_IIR_FENF   0x80
#define UART_IIR_FE     0xC0


#define UART_MCR_LOOP	(0x1 << 4)
#define UART_MCR_OUT2	(0x1 << 3)
#define UART_MCR_OUT1	(0x1 << 2)
#define UART_MCR_RTS	(0x1 << 1)
#define UART_MCR_DTR	(0x1 << 0)


#define UART_MSR_DCD	(0x1 << 7)
#define UART_MSR_RI	    (0x1 << 6)
#define UART_MSR_DSR	(0x1 << 5)
#define UART_MSR_CTS	(0x1 << 4)
#define UART_MSR_DDCD	(0x1 << 3)
#define UART_MSR_TERI	(0x1 << 2)
#define UART_MSR_DDSR	(0x1 << 1)
#define UART_MSR_DCTS	(0x1 << 0)
#define UART_MSR_ANY_DELTA 0x0F

#define UART_LSR_TEMT	(0x1 << 6)
#define UART_LSR_THRE	(0x1 << 5)
#define UART_LSR_BI	    (0x1 << 4)
#define UART_LSR_FE	    (0x1 << 3)
#define UART_LSR_PE	    (0x1 << 2)
#define UART_LSR_OE	    (0x1 << 1)
#define UART_LSR_DR	    (0x1 << 0)
#define UART_LSR_INT_ANY 0x1E


#define UART_FCR_ITL_1      0x00
#define UART_FCR_ITL_2      0x40
#define UART_FCR_ITL_3      0x80
#define UART_FCR_ITL_4      0xC0

#define UART_FCR_DMS        (0x1 << 3)
#define UART_FCR_XFR        (0x1 << 2)
#define UART_FCR_RFR        (0x1 << 1)
#define UART_FCR_FE         (0x1 << 0)


#define UART_FIFO_SIZE   64

#define TYPE_ALLWINNER_H3_UART "allwinner-h3-uart"
#define ALLWINNER_H3_UART(obj) \
    OBJECT_CHECK(AllwinnerH3UartState, (obj), TYPE_ALLWINNER_H3_UART)

typedef struct {
    /* <private> */
    SysBusDevice parent_obj;

    /* <public> */
    MemoryRegion mmio;

    uint32_t uart_rbr;
    uint32_t uart_thr;
    uint32_t uart_dll;
    uint32_t uart_dlh;
    uint32_t uart_ier;
    uint32_t uart_iir;
    uint32_t uart_fcr;
    uint32_t uart_lcr;
    uint32_t uart_mcr;
    uint32_t uart_lsr;
    uint32_t uart_msr;
    uint32_t uart_sch;
    uint32_t uart_usr;
    uint32_t uart_tfl;
    uint32_t uart_rfl;
    uint32_t uart_halt;

    Fifo8 recv_fifo;
    Fifo8 xmit_fifo;

    uint16_t divider;
    int last_break_enable;
    uint32_t baudbase;
    uint8_t tsr;
    uint8_t recv_fifo_itl;
    int thr_ipending;

    CharBackend chr;
    qemu_irq irq;
} AllwinnerH3UartState;
#endif
